#include "preHeader.h"
#include "GameServerMaster.h"
#include "GameServer.h"
#include "Session/CenterSession.h"
#include "Session/SocialServerSession.h"
#include "Session/GateServerListener.h"
#include "Session/MapServerListener.h"
#include "Session/ClientPacketHandler.h"
#include "Session/GateServerSessionHandler.h"
#include "Session/MapServerSessionHandler.h"
#include "Session/CenterSessionHandler.h"
#include "Session/SocialServerSessionHandler.h"
#include "Session/DBPSessionHandler.h"
#include "Session/GateServerMgr.h"
#include "Session/MapServerMgr.h"
#include "WordFilter/WordFilter.h"
#include "Game/AccountMgr.h"
#include "Game/CharacterMgr.h"
#include "Game/TeleportMgr.h"
#include "Mail/MailMgr.h"
#include "Team/TeamMgr.h"
#include "Chat/ChatServer.h"
#include "Session/DBPSession.h"
#include "Manager/InstCfgMgr.h"
#include "Manager/DataMgr.h"
#include "Manager/SpecialShopMgr.h"
#include "Manager/ActivityObjectMgr.h"
#include "Manager/GuildLeagueMgr.h"

GameServerMaster::GameServerMaster()
{
}

GameServerMaster::~GameServerMaster()
{
}

bool GameServerMaster::InitSingleton()
{
	CenterSession::newInstance();
	SocialServerSession::newInstance();
	ClientPacketHandler::newInstance();
	GateServerSessionHandler::newInstance();
	MapServerSessionHandler::newInstance();
	CenterSessionHandler::newInstance();
	SocialServerSessionHandler::newInstance();
	DBPSessionHandler::newInstance();
	MysqlDatabasePool::newInstance();
	DatabaseMgr::newInstance();
	ShellOfGameConfig::newInstance();
	GateServerListener::newInstance();
	MapServerListener::newInstance();
	DBPSessionSingleton::newInstance();
	InstCfgMgr::newInstance();
	DataMgr::newInstance();
	SpecialShopMgr::newInstance();
	ActivityObjectMgr::newInstance();
	GuildLeagueMgr::newInstance();
	GateServerMgr::newInstance();
	MapServerMgr::newInstance();
	WordFilter::newInstance();
	AccountMgr::newInstance();
	CharacterMgr::newInstance();
	TeleportMgr::newInstance();
	MailMgr::newInstance();
	TeamMgr::newInstance();
	ChatServer::newInstance();
	GameServer::newInstance();
	return true;
}

void GameServerMaster::FinishSingleton()
{
	CenterSession::deleteInstance();
	SocialServerSession::deleteInstance();
	ClientPacketHandler::deleteInstance();
	GateServerSessionHandler::deleteInstance();
	MapServerSessionHandler::deleteInstance();
	CenterSessionHandler::deleteInstance();
	SocialServerSessionHandler::deleteInstance();
	DBPSessionHandler::deleteInstance();
	MysqlDatabasePool::deleteInstance();
	DatabaseMgr::deleteInstance();
	ShellOfGameConfig::deleteInstance();
	GateServerListener::deleteInstance();
	MapServerListener::deleteInstance();
	DBPSessionSingleton::deleteInstance();
	InstCfgMgr::deleteInstance();
	DataMgr::deleteInstance();
	SpecialShopMgr::deleteInstance();
	ActivityObjectMgr::deleteInstance();
	GuildLeagueMgr::deleteInstance();
	GateServerMgr::deleteInstance();
	MapServerMgr::deleteInstance();
	WordFilter::deleteInstance();
	AccountMgr::deleteInstance();
	CharacterMgr::deleteInstance();
	TeleportMgr::deleteInstance();
	MailMgr::deleteInstance();
	TeamMgr::deleteInstance();
	ChatServer::deleteInstance();
	GameServer::deleteInstance();
}

bool GameServerMaster::InitDBPool()
{
	const auto& cfg = GetConfig();

	if (!sMysqlDatabasePool.InitWorldDB(
		cfg.GetString("WORLD_DB", "HOST", "127.0.0.1"),
		cfg.GetInteger("WORLD_DB", "PORT", 3306),
		cfg.GetString("WORLD_DB", "USER", "viewer"),
		cfg.GetString("WORLD_DB", "PASSWORD", "123456"),
		cfg.GetString("WORLD_DB", "DATABASE", "mmorpg_world"),
		1, 0))
	{
		return false;
	}

	if (!sMysqlDatabasePool.InitActvtDB(
		cfg.GetString("ACTVT_DB", "HOST", "127.0.0.1"),
		cfg.GetInteger("ACTVT_DB", "PORT", 3306),
		cfg.GetString("ACTVT_DB", "USER", "viewer"),
		cfg.GetString("ACTVT_DB", "PASSWORD", "123456"),
		cfg.GetString("ACTVT_DB", "DATABASE", "mmorpg_actvt"),
		1, 0))
	{
		return false;
	}

	return true;
}

bool GameServerMaster::LoadDBData()
{
	const auto& cfg = GetConfig();
	sDBMgr.SetLang(cfg.GetInteger("OTHER", "LANG", 0));

	DatabaseMgr::SetupActvtDB();
	DatabaseMgr::SetupWorldDB();
	if (!sDBMgr.AsyncLoadAllTables(16)) {
		return false;
	}

	ThreadSafeQueue<std::function<bool()>> tasks;
	tasks.Enqueue([]() {
		return sShellOfGameConfig.LoadNewCfgInst();
	});
	auto threads = std::min(tasks.GetSize(), OS::GetProcNum());
	if (!sDBMgr.WaitFinishTasks(tasks, threads)) {
		return false;
	}

	return true;
}

bool GameServerMaster::StartServices()
{
	const auto& cfg = GetConfig();
	sDBPSession.Init(
		cfg.GetString("DBP_SERVER", "HOST", "127.0.0.1"),
		cfg.GetString("DBP_SERVER", "PORT", "9990"));

	if (!sGateServerListener.Start()) {
		ELOG("--- sGateServerListener.Start() failed.");
		return false;
	}

	if (!sMapServerListener.Start()) {
		ELOG("--- sMapServerListener.Start() failed.");
		return false;
	}

	if (!sGameServer.Start()) {
		ELOG("--- sGameServer.Start() failed.");
		return false;
	}

	return true;
}

void GameServerMaster::StopServices()
{
	sGateServerListener.Stop();
	sMapServerListener.Stop();
	sGameServer.Stop();
}

void GameServerMaster::Tick()
{
	sCenterSession.CheckConnection();
	sSocialServerSession.CheckConnection();
	sDBPSession.CheckConnection();
	sMysqlDatabasePool.GetActvtDB()->CheckConnections();
	sMysqlDatabasePool.GetWorldDB()->CheckConnections();
}

std::string GameServerMaster::GetConfigFile()
{
	return "etc/GameServer.conf";
}

size_t GameServerMaster::GetDeferAsyncServiceCount()
{
	return GetConfig().GetInteger("OTHER", "DEFER_ASYNC_THREAD", 1);
}

size_t GameServerMaster::GetAsyncServiceCount()
{
	return GetConfig().GetInteger("OTHER", "ASYNC_THREAD", 1);
}

size_t GameServerMaster::GetIOServiceCount()
{
	return GetConfig().GetInteger("OTHER", "IO_THREAD", 1);
}
